home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / x11 / xvier.tar / xvier / xvier-1.0 / xvier.c < prev    next >
C/C++ Source or Header  |  1992-07-28  |  39KB  |  1,180 lines

  1. #include <X11/Xlib.h>
  2. #include <X11/Xutil.h>
  3. #include <X11/cursorfont.h>
  4. #include <stdio.h>
  5. #include <signal.h>
  6. #include <sys/types.h>
  7. #include <sys/time.h>
  8.  
  9. #include "xvier.h"
  10.  
  11. char *malloc();
  12.  
  13. char *displayname = NULL, *geostring = NULL, *fontpattern = NULL;
  14. int iconic = 0, level = 0;
  15. int rows = 6, columns = 7;
  16. Display *mydisplay;
  17. int myscreen;
  18. Window topwindow, boardwindow, quitwindow,
  19.        newwindow, undowindow, startwindow, changewindow;
  20. #define TOPBORDERWIDTH 5
  21. #define DEFAULTWIDTH    (((10 + 50 * columns) * 5 + 3) / 4)
  22. #define DEFAULTHEIGHT    (10 + 50 * rows)
  23. #define MINWIDTH    ((DEFAULTWIDTH * 2) / 5)
  24. #define MINHEIGHT    ((DEFAULTHEIGHT * 2) / 5)
  25. #ifndef XVIER_WM_ASPECT_BUG
  26. #define MINASPECTWIDTH    DEFAULTWIDTH
  27. #define MINASPECTHEIGHT    (2 * DEFAULTHEIGHT)
  28. #define MAXASPECTWIDTH    (2 * DEFAULTWIDTH)
  29. #define MAXASPECTHEIGHT    DEFAULTHEIGHT
  30. #endif
  31. GC stonegc[2], buttongc, textgc;
  32. XEvent myevent;
  33. KeySym mykey;
  34. XSizeHints myhint;
  35. XClassHint myclass;
  36. XWMHints *mywmhints;
  37. unsigned long PixelArray[5];
  38. #define WHITE  PixelArray[0]
  39. #define BLACK  PixelArray[1]
  40. #define BLUE   PixelArray[2]
  41. #define YELLOW PixelArray[3]
  42. #define RED    PixelArray[4]
  43. Colormap cmap;
  44. int private_cmap = 0;
  45. Cursor cursor_normal, cursor_q[4];
  46. #include "qup.xbm"
  47. #include "qupm.xbm"
  48. #include "qright.xbm"
  49. #include "qrightm.xbm"
  50. #include "qdown.xbm"
  51. #include "qdownm.xbm"
  52. #include "qleft.xbm"
  53. #include "qleftm.xbm"
  54. Pixmap qup, qupmask, qright, qrightmask, qdown, qdownmask, qleft, qleftmask;
  55. XColor cursorforeground, cursorbackground;
  56. int cursor_num;
  57. #ifndef NO_SELECT
  58. struct timeval selectval;
  59. #endif
  60. unsigned long valuemask;
  61. XSetWindowAttributes attributes;
  62. Pixmap bgpixmap, iconpixmap;
  63. int icon_w_x[6] = {0, 0, 1, 1, 2, 3},
  64.     icon_w_y[6] = {1, 3, 1, 2, 1, 3},
  65.     icon_b_x[6] = {0, 1, 1, 2, 2, 3},
  66.     icon_b_y[6] = {2, 0, 3, 2, 3, 2};
  67. #define DEFAULTICONSIZE 64
  68. #include "patchlevel.h"
  69. char Title[] = XVIER_VERSION;
  70. int c_index = 1, message_index = 0;
  71. char *playercolor[2], levelnumstring[2] = "0",
  72.      *messagestring[5], yellowmovestring[20],
  73.      redmovestring[20];
  74. #define DEFAULTFONTPATTERN "*-Helvetica-Medium-R-Normal-*"
  75. #define MAXFONTS 100
  76. XFontStruct *fontstructarray[MAXFONTS];
  77. int fontnum, quitposx, quitposy, newposx, newposy,
  78.     undoposx, undoposy, startposx, startposy, changeposx, changeposy;
  79. int text1x, text2x, levely, humany, compy, movey;
  80. int topwidth = 0, topheight = 0, boardwidth,
  81.     buttonwidth, buttonheight, buttonspace,
  82.     piece_dx, piece_dy, piece_width, piece_height,
  83.     *stone_x[2], *stone_y[2], stone_n[2] = {0, 0};
  84. XArc *stone[2], *holes;
  85. int pipei[2], pipeo[2], pid, processing;
  86. char *progname = PROGNAME;
  87. #ifdef NO_SELECT
  88. #include <poll.h>
  89. struct pollfd pfd[2];
  90. unsigned long npfd;
  91. #else
  92. #ifdef NO_FD_SET
  93. int readfds, fullfds;
  94. #else
  95. fd_set readfds, fullfds;
  96. #endif
  97. #endif
  98. int *columnfill;
  99.  
  100. struct _rgb_vals {
  101.   unsigned short red, green, blue;
  102. } color_values[5] = {
  103.     { 65535, 65535, 65535 },
  104.     {     0,     0,     0 },
  105.     {     0,     0, 65535 },
  106.     { 65535, 65535,     0 },
  107.     { 65535,     0,     0 }},
  108.   gray_values[5] = {
  109.     { 65535, 65535, 65535 },
  110.     {     0,     0,     0 },
  111.     { 32767, 32767, 32767 },
  112.     { 65535, 65535, 65535 },
  113.     {     0,     0,     0 }},
  114.   *rgb_values;
  115.  
  116. int font_cmp(p1, p2)
  117. XFontStruct **p1, **p2;
  118. {
  119.   int ret = ((*p1)->max_bounds.rbearing + (*p1)->max_bounds.lbearing) -
  120.         ((*p2)->max_bounds.rbearing + (*p2)->max_bounds.lbearing);
  121.  
  122.   if (ret == 0)
  123.     ret = ((*p1)->max_bounds.ascent + (*p1)->max_bounds.descent) -
  124.       ((*p2)->max_bounds.ascent + (*p2)->max_bounds.descent);
  125.   return ret;
  126. }
  127.  
  128. void change_cursor()
  129. {
  130.   if (cursor_num == 3)
  131.     cursor_num = 0;
  132.   else
  133.     cursor_num++;
  134.   XDefineCursor(mydisplay, topwindow, cursor_q[cursor_num]);
  135. }
  136.  
  137. void write_prog(ch)
  138. char ch;
  139. {
  140.   if (processing)
  141.     XBell(mydisplay, 0);
  142.   else {
  143.     if (write(pipeo[1], &ch, 1) < 1) {
  144.       perror("write to xvier_prog failed");
  145.       exit(1);
  146.     }
  147.     processing = 1;
  148.     cursor_num = 0;
  149.     XDefineCursor(mydisplay, topwindow, cursor_q[0]);
  150.   }
  151. }
  152.  
  153. void message(newindex)
  154. int newindex;
  155. {
  156.   message_index = newindex;
  157.   XClearArea(mydisplay, topwindow, boardwidth,
  158.          topheight - movey + compy, 0, 0, False);
  159.   XDrawImageString(mydisplay, topwindow, textgc, text1x, movey,
  160.            messagestring[newindex], strlen(messagestring[newindex]));
  161. }
  162.  
  163. void domove(ind, col)
  164. int ind, col;
  165. {
  166.   int n = stone_n[ind]++;
  167.  
  168.   stone_x[ind][n] = col;
  169.   stone_y[ind][n] = columnfill[col]++;
  170.   stone[ind][n].x = piece_dx + stone_x[ind][n] * (piece_dx + piece_width);
  171.   stone[ind][n].y = piece_dy +
  172.     (rows - 1 - stone_y[ind][n]) * (piece_dy + piece_height);
  173.   stone[ind][n].width = piece_width;
  174.   stone[ind][n].height = piece_height;
  175.   XFillArc(mydisplay, boardwindow, stonegc[ind], stone[ind][n].x,
  176.        stone[ind][n].y, piece_width, piece_height, 0, 360 * 64);
  177. }
  178.  
  179. void undomove(ind)
  180. int ind;
  181. {
  182.   int n = --stone_n[ind], col = stone_x[ind][n];
  183.  
  184.   columnfill[col]--;
  185.   XClearArea(mydisplay, boardwindow, piece_dx / 2 +
  186.          col * (piece_dx + piece_width), piece_dy / 2 +
  187.          (rows - 1 - stone_y[ind][n]) * (piece_dy + piece_height),
  188.          piece_dx + piece_width, piece_dy + piece_height, False);
  189.   XDrawArc(mydisplay, boardwindow, textgc, 1 + piece_dx +
  190.        col * (piece_dx + piece_width), 1 + piece_dy +
  191.        (rows - 1 - stone_y[ind][n]) * (piece_dy + piece_height),
  192.        piece_width - 2, piece_height - 2, 0, 360 * 64);
  193. }
  194.  
  195. void recalculate(width, height)
  196. int width, height;
  197. {
  198.   int i, j, fontid, d1, d2, d3, maxtextwidth, maxtextheight;
  199.   XCharStruct tmpsize;
  200.  
  201.   if (width == topwidth && height == topheight)
  202.     return;
  203.   topwidth = width;
  204.   topheight = height;
  205.   boardwidth = (topwidth * 4) / 5;
  206.   buttonspace = (topwidth - boardwidth) / 10;
  207.   buttonwidth = (topwidth - boardwidth) - 2 * buttonspace;
  208.   buttonheight = (topheight / 2 - 4 * buttonspace) / 4;
  209.   if (buttonheight < 2 * buttonspace) {
  210.     buttonspace = topheight / 24;
  211.     buttonwidth = (topwidth - boardwidth) - 2 * buttonspace;
  212.     buttonheight = (topheight / 2 - 4 * buttonspace) / 4;
  213.   }
  214.   for (i = 0; i < fontnum; i++) {
  215.     int cpx, cpy, qpx, qpy, npx, npy, upx, upy;
  216.  
  217.     XTextExtents(fontstructarray[i], "Change", 6, &d1, &d2, &d3, &tmpsize);
  218.     if (i > 0 && (tmpsize.rbearing + tmpsize.lbearing > buttonwidth - 2 ||
  219.           tmpsize.ascent + tmpsize.descent > buttonheight - 2))
  220.       continue;
  221.     cpx = (buttonwidth - tmpsize.lbearing - tmpsize.rbearing) / 2 +
  222.       tmpsize.lbearing;
  223.     cpy = (buttonheight - tmpsize.ascent - tmpsize.descent) / 2 +
  224.       tmpsize.ascent;
  225.     XTextExtents(fontstructarray[i], "Quit", 4, &d1, &d2, &d3, &tmpsize);
  226.     if (i > 0 && (tmpsize.rbearing + tmpsize.lbearing > buttonwidth - 2 ||
  227.           tmpsize.ascent + tmpsize.descent > buttonheight - 2))
  228.       continue;
  229.     qpx = (buttonwidth - tmpsize.lbearing - tmpsize.rbearing) / 2 +
  230.       tmpsize.lbearing;
  231.     qpy = (buttonheight - tmpsize.ascent - tmpsize.descent) / 2 +
  232.       tmpsize.ascent;
  233.     XTextExtents(fontstructarray[i], "New", 3, &d1, &d2, &d3, &tmpsize);
  234.     if (i > 0 && (tmpsize.rbearing + tmpsize.lbearing > buttonwidth - 2 ||
  235.           tmpsize.ascent + tmpsize.descent > buttonheight - 2))
  236.       continue;
  237.     npx = (buttonwidth - tmpsize.lbearing - tmpsize.rbearing) / 2 +
  238.       tmpsize.lbearing;
  239.     npy = (buttonheight - tmpsize.ascent - tmpsize.descent) / 2 +
  240.       tmpsize.ascent;
  241.     XTextExtents(fontstructarray[i], "Undo", 4, &d1, &d2, &d3, &tmpsize);
  242.     if (i > 0 && (tmpsize.rbearing + tmpsize.lbearing > buttonwidth - 2 ||
  243.           tmpsize.ascent + tmpsize.descent > buttonheight - 2))
  244.       continue;
  245.     upx = (buttonwidth - tmpsize.lbearing - tmpsize.rbearing) / 2 +
  246.       tmpsize.lbearing;
  247.     upy = (buttonheight - tmpsize.ascent - tmpsize.descent) / 2 +
  248.       tmpsize.ascent;
  249.     XTextExtents(fontstructarray[i], "Start", 5, &d1, &d2, &d3, &tmpsize);
  250.     if (i > 0 && (tmpsize.rbearing + tmpsize.lbearing > buttonwidth - 2 ||
  251.           tmpsize.ascent + tmpsize.descent > buttonheight - 2))
  252.       continue;
  253.     changeposx = cpx; changeposy = cpy;
  254.     quitposx = qpx; quitposy = qpy;
  255.     newposx = npx; newposy = npy;
  256.     undoposx = upx; undoposy = upy;
  257.     startposx = (buttonwidth - tmpsize.lbearing - tmpsize.rbearing) / 2 +
  258.       tmpsize.lbearing;
  259.     startposy = (buttonheight - tmpsize.ascent - tmpsize.descent) / 2 +
  260.       tmpsize.ascent;
  261.     fontid = fontstructarray[i]->fid;
  262.   }
  263.   XSetFont(mydisplay, buttongc, fontid);
  264.   maxtextheight = (topheight  - 5 * (buttonspace + buttonheight)) / 5;
  265.   maxtextwidth = topwidth - boardwidth - maxtextheight / 4;
  266.   for (i = 0; i < fontnum; i++) {
  267.     int max1x = 0, max2x = 0, j;
  268.  
  269.     if (i > 0) {
  270.       if (fontstructarray[i]->max_bounds.ascent +
  271.       fontstructarray[i]->max_bounds.descent > maxtextheight)
  272.     goto next_font;
  273.       for (j = 0; j < 5; j++) {
  274.     XTextExtents(fontstructarray[i], messagestring[j],
  275.              strlen(messagestring[j]), &d1, &d2, &d3, &tmpsize);
  276.     if (tmpsize.rbearing +
  277.         fontstructarray[i]->max_bounds.lbearing > maxtextwidth)
  278.       goto next_font;
  279.       }
  280.     }
  281.     XTextExtents(fontstructarray[i], "Level: ", 7,
  282.          &d1, &d2, &d3, &tmpsize);
  283.     if (tmpsize.rbearing > max1x)
  284.       max1x = tmpsize.rbearing;
  285.     XTextExtents(fontstructarray[i], "You: ", 5,
  286.          &d1, &d2, &d3, &tmpsize);
  287.     if (tmpsize.rbearing > max1x)
  288.       max1x = tmpsize.rbearing;
  289.     XTextExtents(fontstructarray[i], "Me: ", 4,
  290.          &d1, &d2, &d3, &tmpsize);
  291.     if (tmpsize.rbearing > max1x)
  292.       max1x = tmpsize.rbearing;
  293.     XTextExtents(fontstructarray[i], playercolor[0], strlen(playercolor[0]),
  294.          &d1, &d2, &d3, &tmpsize);
  295.     if (tmpsize.rbearing > max2x)
  296.       max2x = tmpsize.rbearing;
  297.     XTextExtents(fontstructarray[i], playercolor[1], strlen(playercolor[1]),
  298.          &d1, &d2, &d3, &tmpsize);
  299.     if (tmpsize.rbearing > max2x)
  300.       max2x = tmpsize.rbearing;
  301.     if (i > 0 && max1x + max2x +
  302.     2 * fontstructarray[i]->max_bounds.lbearing > maxtextwidth)
  303.       goto next_font;
  304.     fontid = fontstructarray[i]->fid;
  305.     text1x  = boardwidth + fontstructarray[i]->max_bounds.lbearing +
  306.       (topwidth - boardwidth - maxtextwidth) / 2;
  307.     text2x = text1x + max1x  + fontstructarray[i]->max_bounds.lbearing;
  308.     movey = topheight - maxtextheight / 8 -
  309.       fontstructarray[i]->max_bounds.descent -
  310.     (maxtextheight - fontstructarray[i]->max_bounds.ascent -
  311.      fontstructarray[i]->max_bounds.descent) / 2;
  312.     compy = movey - maxtextheight - maxtextheight / 4;
  313.     humany = compy - maxtextheight - maxtextheight / 4;
  314.     levely = humany - maxtextheight - maxtextheight / 4;
  315.   next_font:
  316.     ;
  317.   }
  318.   XSetFont(mydisplay, textgc, fontid);
  319.   piece_dx = boardwidth / (columns * 5 + 1);
  320.   piece_width = (boardwidth - (columns + 1) * piece_dx) / columns;
  321.   piece_dy = topheight / (rows * 5 + 1);
  322.   piece_height = (topheight - (rows + 1) * piece_dy) / rows;
  323.   for (i = 0; i < stone_n[0]; i++) {
  324.     stone[0][i].x = piece_dx + stone_x[0][i] * (piece_dx + piece_width);
  325.     stone[0][i].y = piece_dy +
  326.       (rows - 1 - stone_y[0][i]) * (piece_dy + piece_height);
  327.     stone[0][i].width = piece_width;
  328.     stone[0][i].height = piece_height;
  329.   }
  330.   for (i = 0; i < stone_n[1]; i++) {
  331.     stone[1][i].x = piece_dx + stone_x[1][i] * (piece_dx + piece_width);
  332.     stone[1][i].y = piece_dy +
  333.       (rows - 1 - stone_y[1][i]) * (piece_dy + piece_height);
  334.     stone[1][i].width = piece_width;
  335.     stone[1][i].height = piece_height;
  336.   }
  337.   for (i = 0; i < rows; i++)
  338.     for (j = 0; j < columns; j++) {
  339.       holes[i*columns+j].x = 1 + piece_dx + j * (piece_dx + piece_width);
  340.       holes[i*columns+j].y = 1 + piece_dy + i * (piece_dy + piece_height);
  341.       holes[i*columns+j].width = piece_width - 2;
  342.       holes[i*columns+j].height = piece_height - 2;
  343.     }
  344.   XResizeWindow(mydisplay, boardwindow, boardwidth, topheight);
  345.   XMoveResizeWindow(mydisplay, quitwindow, boardwidth + buttonspace,
  346.             buttonspace, buttonwidth, buttonheight);
  347.   XMoveResizeWindow(mydisplay, newwindow, boardwidth + buttonspace,
  348.             2 * buttonspace + buttonheight,
  349.             buttonwidth, buttonheight);
  350.   XMoveResizeWindow(mydisplay, undowindow, boardwidth + buttonspace,
  351.             buttonspace + 2 * (buttonheight + buttonspace),
  352.             buttonwidth, buttonheight);
  353.   XMoveResizeWindow(mydisplay, startwindow, boardwidth + buttonspace,
  354.             buttonspace + 3 * (buttonheight + buttonspace),
  355.             buttonwidth, buttonheight);
  356.   XMoveResizeWindow(mydisplay, changewindow, boardwidth + buttonspace,
  357.             buttonspace + 4 * (buttonheight + buttonspace),
  358.             buttonwidth, buttonheight);
  359.   XSetWindowBorderWidth(mydisplay, quitwindow,
  360.             ((buttonspace / 8 < 1) ? 1 : buttonspace / 8));
  361.   XSetWindowBorderWidth(mydisplay, newwindow,
  362.             ((buttonspace / 8 < 1) ? 1 : buttonspace / 8));
  363.   XSetWindowBorderWidth(mydisplay, undowindow,
  364.             ((buttonspace / 8 < 1) ? 1 : buttonspace / 8));
  365.   XSetWindowBorderWidth(mydisplay, startwindow,
  366.             ((buttonspace / 8 < 1) ? 1 : buttonspace / 8));
  367.   XSetWindowBorderWidth(mydisplay, changewindow,
  368.             ((buttonspace / 8 < 1) ? 1 : buttonspace / 8));
  369. }
  370.  
  371. #define Repaint_topwindow() XClearArea(mydisplay, topwindow, boardwidth,\
  372.                   5 * (buttonspace + buttonheight), 0, 0, True)
  373.  
  374. int main(argc, argv)
  375. int    argc;
  376. char **argv;
  377. {
  378.   char text[10], **fontnames, *av[4], row_string[3], column_string[3];
  379.   int i, j, geo_ret, userx, usery, userwidth, userheight;
  380.   int iconsize, Ilistsize;
  381.   XIconSize *Ilist;
  382.  
  383.   for (i = 1; i < argc; i++) {
  384.     if (strcmp(argv[i], "-display") == 0)
  385.       if (++i == argc)
  386.     goto usage;
  387.       else
  388.     displayname = argv[i];
  389.     else if (strcmp(argv[i], "-geometry") == 0)
  390.       if (++i == argc)
  391.     goto usage;
  392.       else
  393.     geostring = argv[i];
  394.     else if (strcmp(argv[i], "-fn") == 0)
  395.       if (++i == argc)
  396.     goto usage;
  397.       else
  398.     fontpattern = argv[i];
  399.     else if (strcmp(argv[i], "-prog") == 0)
  400.       if (++i == argc)
  401.     goto usage;
  402.       else
  403.     progname = argv[i];
  404.     else if (strcmp(argv[i], "-rows") == 0)
  405.       if (++i == argc)
  406.     goto usage;
  407.       else {
  408.     if ((rows = atoi(argv[i])) < 4 || rows > MAXRC)
  409.       goto usage;
  410.       }
  411.     else if (strcmp(argv[i], "-columns") == 0)
  412.       if (++i == argc)
  413.     goto usage;
  414.       else {
  415.     if ((columns = atoi(argv[i])) < 4 || columns > MAXRC)
  416.       goto usage;
  417.       }
  418.     else if (strcmp(argv[i], "-iconic") == 0)
  419.       iconic++;
  420.     else if (strcmp(argv[i], "-level") == 0)
  421.       if (++i == argc)
  422.     goto usage;
  423.       else {
  424.     if (argv[i][0] == '+' ||
  425.         ('0' <= argv[i][0] && argv[i][0] <= '9'))
  426.       level = atoi(argv[i]);
  427.     else
  428.       level = -1;
  429.     if (level < 0 || level > 9) {
  430.       fprintf(stderr, "%s: level should be in the range 0..9\n", *argv);
  431.       exit(1);
  432.     }
  433.       }
  434.     else {
  435.     usage:
  436.       fprintf(stderr, "usage: %s\t[-display <display>]\
  437. \n\t\t[-geometry <geometry>]\n\t\t[-fn <fontpattern>]\n\t\t[-iconic]\
  438. \n\t\t[-rows <rows>]\n\t\t[-columns <columns>]\
  439. \n\t\t[-prog <path>]\n\t\t[-level <num>]\n", *argv);
  440.       exit(1);
  441.     }
  442.   }
  443.   if ((mydisplay = XOpenDisplay(displayname)) == NULL) {
  444.     if (displayname != NULL)
  445.       fprintf(stderr, "%s: Couldn't open display \"%s\".\n",
  446.           *argv, displayname);
  447.     else
  448.       fprintf(stderr, "%s: Couldn't open display.\n", *argv);
  449.     exit(1);
  450.   }
  451.   if (pipe(pipeo) < 0 || pipe(pipei) < 0) {
  452.     perror("xvier pipe failed");
  453.     exit(1);
  454.   }
  455.   switch (pid = fork()) {
  456.   case -1:
  457.     perror("xvier fork failed");
  458.     exit(1);
  459.   case 0:
  460.     if (dup2(pipeo[0], 0) < 0 || dup2(pipei[1], 1) < 0) {
  461.       perror("xvier dup2 failed");
  462.       exit(1);
  463.     }
  464. #ifdef NO_GETDTABSIZE
  465. #ifdef hpux
  466.     for (i = _NFILE; i > 2; i--)
  467. #else
  468.     for (i = sysconf(_SC_OPEN_MAX); i > 2; i--)
  469. #endif
  470. #else
  471.     for (i = getdtablesize(); i > 2; i--)
  472. #endif
  473.       close(i);
  474.     for (i = 0; i < NSIG; i++)
  475.       signal(i, SIG_DFL);
  476.     sprintf(row_string, "%d", rows);
  477.     sprintf(column_string, "%d", columns);
  478.     av[0] = "xvier_prog";
  479.     av[1] = row_string;
  480.     av[2] = column_string;
  481.     av[3] = (char *) NULL;
  482.     execvp(progname, av);
  483.     perror("xvier child exec");
  484.     exit(1);
  485.   default:
  486.     close(pipeo[0]);
  487.     close(pipei[1]);
  488.   }
  489. #ifdef NO_SELECT
  490.   pfd[0].fd = ConnectionNumber(mydisplay);
  491.   pfd[1].fd = pipei[0];
  492.   pfd[0].events = pfd[1].events = POLLIN;
  493.   npfd = 2L;
  494. #else
  495. #ifdef NO_FD_SET
  496.   fullfds = (1 << ConnectionNumber(mydisplay)) | (1 << pipei[0]);
  497. #else
  498.   FD_ZERO(&fullfds);
  499.   FD_SET(ConnectionNumber(mydisplay), &fullfds);
  500.   FD_SET(pipei[0], &fullfds);
  501. #endif
  502. #endif
  503.   for (i = 0; i < 6; i++) {
  504.     if (read(pipei[0], &text[i], 1) < 1) {
  505.       fprintf(stderr, "%s: read from xvier_prog failed\n", *argv);
  506.       exit(1);
  507.     }
  508.     if (text[i] == 'C') {
  509.       text[i+1] = '\0';
  510.       break;
  511.     }
  512.   }
  513.   text[6] = '\0';
  514.   if (sscanf(text, "%dR%dC", &rows, &columns) != 2 ||
  515.       rows < 4 || rows > MAXRC || columns < 4 || columns > MAXRC) {
  516.     fprintf(stderr, "%s: wrong format from xvier_prog\n", *argv);
  517.     exit(1);
  518.   }
  519.   columnfill = (int *)malloc(columns * sizeof(int));
  520.   for (i = 0; i < columns; i++)
  521.     columnfill[i] = 0;
  522.   stone_x[0] = (int *)malloc(((columns * rows + 1) >> 1) * sizeof(int));
  523.   stone_x[1] = (int *)malloc(((columns * rows + 1) >> 1) * sizeof(int));
  524.   stone_y[0] = (int *)malloc(((columns * rows + 1) >> 1) * sizeof(int));
  525.   stone_y[1] = (int *)malloc(((columns * rows + 1) >> 1) * sizeof(int));
  526.   stone[0] = (XArc *)malloc(((columns * rows + 1) >> 1) * sizeof(XArc));
  527.   stone[1] = (XArc *)malloc(((columns * rows + 1) >> 1) * sizeof(XArc));
  528.   holes = (XArc *)malloc((columns * rows) * sizeof(XArc));
  529.   myscreen = DefaultScreen(mydisplay);
  530.   if (geostring != NULL) {
  531.     char defaultstring[10];
  532.  
  533.     sprintf(defaultstring, "%dx%d", DEFAULTWIDTH, DEFAULTHEIGHT);
  534.     geo_ret = XGeometry(mydisplay, myscreen, geostring, defaultstring,
  535.             TOPBORDERWIDTH, 1, 1, 0, 0,
  536.             &userx, &usery, &userwidth, &userheight);
  537.   } else
  538.     geo_ret = 0;
  539.   for (i = 0; i < ((columns * rows + 1) >> 1); i++) {
  540.     stone[0][i].angle1 = stone[1][i].angle1 = 0;
  541.     stone[0][i].angle2 = stone[1][i].angle2 = 360 * 64;
  542.   }
  543.   for (i = 0; i < columns * rows; i++) {
  544.     holes[i].angle1 = 0;
  545.     holes[i].angle2 = 360 * 64;
  546.   }
  547.   valuemask = 0;
  548.   playercolor[0] = "WHITE";
  549.   playercolor[1] = "BLACK";
  550.   if (DefaultDepth(mydisplay, myscreen) == 1) {
  551.     WHITE = YELLOW = WhitePixel(mydisplay, myscreen);
  552.     BLACK = BLUE = RED = BlackPixel(mydisplay, myscreen);
  553.   } else {
  554.     Visual *vis = DefaultVisual(mydisplay, myscreen);
  555.  
  556.     if (vis->class == GrayScale || vis->class == StaticGray ||
  557.     vis->map_entries < 5)
  558.       rgb_values = gray_values;
  559.     else {
  560.       rgb_values = color_values;
  561.       playercolor[0] = "YELLOW";
  562.       playercolor[1] = "RED";
  563.     }
  564.     cmap = DefaultColormap(mydisplay, myscreen);
  565.     for (i = 0; i < 5; i++) {
  566.       XColor color;
  567.  
  568.       color.red   = rgb_values[i].red;
  569.       color.green = rgb_values[i].green;
  570.       color.blue  = rgb_values[i].blue;
  571.       color.flags = DoRed | DoGreen | DoBlue;
  572.     retry:
  573.       if (XAllocColor(mydisplay, cmap, &color) == 0)
  574.     if (!private_cmap) {
  575.       private_cmap = 1;
  576.       cmap = XCopyColormapAndFree(mydisplay, cmap);
  577.       goto retry;
  578.     } else {
  579.       fprintf(stderr, "%s: Couldn't allocate color %d\n", *argv, i);
  580.       exit(2);
  581.     }
  582.       PixelArray[i] = color.pixel;
  583.     }
  584.     if (private_cmap) {
  585.       attributes.colormap = cmap;
  586.       valuemask |= CWColormap;
  587.     }
  588.   }
  589.   sprintf(yellowmovestring, "%s to move", playercolor[0]);
  590.   sprintf(redmovestring, "%s to move", playercolor[1]);
  591.   messagestring[0] = yellowmovestring;
  592.   messagestring[1] = redmovestring;
  593.   messagestring[2] = "I win";
  594.   messagestring[3] = "You win!";
  595.   messagestring[4] = "Draw";
  596.   attributes.background_pixel = WHITE;
  597.   valuemask |= CWBackPixel;
  598.   attributes.border_pixel = BLACK;
  599.   valuemask |= CWBorderPixel;
  600.   attributes.cursor = cursor_normal = XCreateFontCursor(mydisplay, XC_hand2);
  601.   valuemask |= CWCursor;
  602.   attributes.event_mask = KeyPressMask | ExposureMask | StructureNotifyMask;
  603.   valuemask |= CWEventMask;
  604.   attributes.do_not_propagate_mask = ButtonPressMask;
  605.   valuemask |= CWDontPropagate;
  606.   switch (geo_ret & (WidthValue | HeightValue)) {
  607.   case 0:
  608.     myhint.width = DEFAULTWIDTH;
  609.     myhint.height = DEFAULTHEIGHT;
  610.     myhint.flags = PSize;
  611.     break;
  612.   case WidthValue | HeightValue:
  613.     if (userwidth < MINWIDTH) {
  614.       if (geo_ret & XNegative)
  615.     userx += userwidth - MINWIDTH;
  616.       userwidth = MINWIDTH;
  617.     }
  618.     if (userheight < MINHEIGHT) {
  619.       if (geo_ret & YNegative)
  620.     usery += userheight - MINHEIGHT;
  621.       userheight = MINHEIGHT;
  622.     }
  623. #ifndef XVIER_WM_ASPECT_BUG
  624.     if (userwidth * MINASPECTHEIGHT < userheight * MINASPECTWIDTH) {
  625.       if (geo_ret & XNegative)
  626.     userx += userwidth -
  627.       (userheight * MINASPECTWIDTH) / MINASPECTHEIGHT;
  628.       userwidth = (userheight * MINASPECTWIDTH) / MINASPECTHEIGHT;
  629.     }
  630.     if (userwidth * MAXASPECTHEIGHT > userheight * MAXASPECTWIDTH) {
  631.       if (geo_ret & YNegative)
  632.     usery += userheight -
  633.       (userwidth * MAXASPECTHEIGHT) / MAXASPECTWIDTH;
  634.       userheight = (userwidth * MAXASPECTHEIGHT) / MAXASPECTWIDTH;
  635.     }
  636. #endif
  637.     myhint.width = userwidth;
  638.     myhint.height = userheight;
  639.     myhint.flags = USSize;
  640.     break;
  641.   case WidthValue:
  642.     if (userwidth < MINWIDTH) {
  643.       if (geo_ret & XNegative)
  644.     userx += userwidth - MINWIDTH;
  645.       userwidth = MINWIDTH;
  646.     }
  647.     if (geo_ret & YNegative)
  648.       usery += DEFAULTHEIGHT - (userwidth * DEFAULTHEIGHT) / DEFAULTWIDTH;
  649.     myhint.width = userwidth;
  650.     myhint.height = (userwidth * DEFAULTHEIGHT) / DEFAULTWIDTH;
  651.     myhint.flags = USSize;
  652.     break;
  653.   case HeightValue:
  654.     if (userheight < MINHEIGHT) {
  655.       if (geo_ret & YNegative)
  656.     usery += userheight - MINHEIGHT;
  657.       userheight = MINHEIGHT;
  658.     }
  659.     if (geo_ret & XNegative)
  660.       userx += DEFAULTWIDTH - (userheight * DEFAULTWIDTH) / DEFAULTHEIGHT;
  661.     myhint.width = (userheight * DEFAULTWIDTH) / DEFAULTHEIGHT;
  662.     myhint.height = userheight;
  663.     myhint.flags = USSize;
  664.     break;
  665.   }
  666.   if (geo_ret & XValue)
  667.     myhint.x = userx;
  668.   else
  669.     myhint.x = (DisplayWidth(mydisplay, myscreen) - myhint.width) / 2;
  670.   if (geo_ret & YValue)
  671.     myhint.y = usery;
  672.   else
  673.     myhint.y = (DisplayHeight(mydisplay, myscreen) - myhint.height) / 2;
  674.   if (geo_ret & (XValue | YValue))
  675.     myhint.flags |= USPosition;
  676.   else
  677.     myhint.flags |= PPosition;
  678.   topwindow = XCreateWindow(mydisplay, DefaultRootWindow(mydisplay),
  679.                 myhint.x, myhint.y, myhint.width, myhint.height,
  680.                 TOPBORDERWIDTH, CopyFromParent, InputOutput,
  681.                 CopyFromParent, valuemask, &attributes);
  682.   qup = XCreateBitmapFromData(mydisplay, topwindow, qup_bits,
  683.                   qup_width, qup_height);
  684.   qupmask = XCreateBitmapFromData(mydisplay, topwindow, qupmask_bits,
  685.                   qupmask_width, qupmask_height);
  686.   qright = XCreateBitmapFromData(mydisplay, topwindow, qright_bits,
  687.                  qright_width, qright_height);
  688.   qrightmask = XCreateBitmapFromData(mydisplay, topwindow, qrightmask_bits,
  689.                      qrightmask_width, qrightmask_height);
  690.   qdown = XCreateBitmapFromData(mydisplay, topwindow, qdown_bits,
  691.                 qdown_width, qdown_height);
  692.   qdownmask = XCreateBitmapFromData(mydisplay, topwindow, qdownmask_bits,
  693.                     qdownmask_width, qdownmask_height);
  694.   qleft = XCreateBitmapFromData(mydisplay, topwindow, qleft_bits,
  695.                 qleft_width, qleft_height);
  696.   qleftmask = XCreateBitmapFromData(mydisplay, topwindow, qleftmask_bits,
  697.                     qleftmask_width, qleftmask_height);
  698.   cursorforeground.red = cursorforeground.green = cursorforeground.blue = 0;
  699.   cursorforeground.flags = DoRed | DoGreen | DoBlue;
  700.   cursorbackground.red = cursorbackground.green = cursorbackground.blue = 65535;
  701.   cursorbackground.flags = DoRed | DoGreen | DoBlue;
  702.   if ((cursor_q[0] = XCreatePixmapCursor(mydisplay, qup, qupmask,
  703.                      &cursorforeground, &cursorbackground,
  704.                      qup_x_hot, qup_y_hot)) == None ||
  705.       (cursor_q[1] = XCreatePixmapCursor(mydisplay, qright, qrightmask,
  706.                      &cursorforeground, &cursorbackground,
  707.                      qright_x_hot, qright_y_hot)) == None ||
  708.       (cursor_q[2] = XCreatePixmapCursor(mydisplay, qdown, qdownmask,
  709.                      &cursorforeground, &cursorbackground,
  710.                      qdown_x_hot, qdown_y_hot)) == None ||
  711.       (cursor_q[3] = XCreatePixmapCursor(mydisplay, qleft, qleftmask,
  712.                      &cursorforeground, &cursorbackground,
  713.                      qleft_x_hot, qleft_y_hot)) == None) {
  714.     fprintf(stderr, "%s: couldn't create cursors\n", *argv);
  715.     exit(1);
  716.   }
  717. #ifndef NO_SELECT
  718.   selectval.tv_sec = 0;
  719.   selectval.tv_usec = 500000;
  720. #endif
  721.   iconsize = 0;
  722.   if (XGetIconSizes(mydisplay, topwindow, &Ilist, &Ilistsize) != 0)
  723.     for (i = 0; i < Ilistsize; i++) {
  724.       if (Ilist[i].max_width < Ilist[i].max_height) {
  725.     if (Ilist[i].max_width > iconsize &&
  726.         (Ilist[i].max_width == Ilist[i].max_height ||
  727.          (Ilist[i].max_width < Ilist[i].max_height &&
  728.           Ilist[i].max_width >= Ilist[i].min_height &&
  729.           (Ilist[i].max_width - Ilist[i].min_height) %
  730.           Ilist[i].height_inc == 0)))
  731.       iconsize = Ilist[i].max_width;
  732.       } else
  733.     if (Ilist[i].max_height > iconsize &&
  734.         (Ilist[i].max_height == Ilist[i].max_width ||
  735.          (Ilist[i].max_height < Ilist[i].max_width &&
  736.           Ilist[i].max_height >= Ilist[i].min_width &&
  737.           (Ilist[i].max_height - Ilist[i].min_width) %
  738.           Ilist[i].width_inc == 0)))
  739.       iconsize = Ilist[i].max_height;
  740.     }
  741.   if (iconsize == 0)
  742.     iconsize = DEFAULTICONSIZE;
  743.   {
  744.     GC iconpgc;
  745.     int spacing, width;
  746.  
  747.     spacing = iconsize / 16;
  748.     width = (iconsize - 4 * spacing) / 4;
  749.     iconpixmap = XCreatePixmap(mydisplay, DefaultRootWindow(mydisplay),
  750.                    iconsize, iconsize, 1);
  751.     iconpgc = XCreateGC(mydisplay, iconpixmap, 0, 0);
  752.     XSetForeground(mydisplay, iconpgc, 0L);
  753.     XFillRectangle(mydisplay, iconpixmap, iconpgc, 0, 0, iconsize, iconsize);
  754.     XSetForeground(mydisplay, iconpgc, ~0L);
  755.     for (i = 0; i < 6; i++)
  756.       XDrawArc(mydisplay, iconpixmap, iconpgc,
  757.            spacing / 2 + icon_w_x[i] * (spacing + width),
  758.            spacing / 2 + icon_w_y[i] * (spacing + width),
  759.            width, width, 0, 360 * 64);
  760.     for (i = 0; i < 6; i++)
  761.       XFillArc(mydisplay, iconpixmap, iconpgc,
  762.            spacing / 2 + icon_b_x[i] * (spacing + width),
  763.            spacing / 2 + icon_b_y[i] * (spacing + width),
  764.            width, width, 0, 360 * 64);
  765.     XFreeGC(mydisplay, iconpgc);
  766.   }
  767.   myhint.min_width = MINWIDTH;
  768.   myhint.min_height = MINHEIGHT;
  769.   myhint.flags |= PMinSize;
  770. #ifndef XVIER_WM_ASPECT_BUG
  771.   myhint.min_aspect.x = MINASPECTWIDTH;
  772.   myhint.min_aspect.y = MINASPECTHEIGHT;
  773.   myhint.max_aspect.x = MAXASPECTWIDTH;
  774.   myhint.max_aspect.y = MAXASPECTHEIGHT;
  775.   myhint.flags |= PAspect;
  776. #endif
  777.   XSetStandardProperties(mydisplay, topwindow, Title, Title, iconpixmap,
  778.              argv, argc, &myhint);
  779.   myclass.res_name = "xvier";
  780.   myclass.res_class = "Xvier";
  781.   XSetClassHint(mydisplay, topwindow, &myclass);
  782.   if (iconic) {
  783.     mywmhints = XGetWMHints(mydisplay, topwindow);
  784.     mywmhints->initial_state = IconicState;
  785.     mywmhints->flags |= StateHint;
  786.     XSetWMHints(mydisplay, topwindow, mywmhints);
  787.   }
  788.   valuemask = 0;
  789.   if (DefaultDepth(mydisplay, myscreen) == 1) {
  790.     unsigned int w, h, w_8;
  791.     char *data;
  792.  
  793.     XQueryBestStipple(mydisplay, topwindow, 8, 8, &w, &h);
  794.     if (w & 1)
  795.       w *= 2;
  796.     if (h & 1)
  797.       h *= 2;
  798.     w_8 = (w + 7) / 8;
  799.     data = malloc(w_8 * h);
  800.     for (j = 0; j < h; j++)
  801.       for (i = 0; i < w_8; i++)
  802.     data[j * w_8 + i] = ((j & 1) ? 0xaa : 0x55);
  803.     bgpixmap = XCreateBitmapFromData(mydisplay, topwindow, data, w, h);
  804.     attributes.background_pixmap = bgpixmap;
  805.     valuemask |= CWBackPixmap;
  806.     free(data);
  807.   } else {
  808.     attributes.background_pixel = BLUE;
  809.     valuemask |= CWBackPixel;
  810.   }
  811.   attributes.event_mask = ButtonPressMask | ExposureMask;
  812.   valuemask |= CWEventMask;
  813.   attributes.override_redirect = True;
  814.   valuemask |= CWOverrideRedirect;
  815.   attributes.win_gravity = UnmapGravity;
  816.   valuemask |= CWWinGravity;
  817.   boardwindow = XCreateWindow(mydisplay, topwindow, 0, 0, 10, 10, 0,
  818.                   CopyFromParent, InputOutput, CopyFromParent,
  819.                   valuemask, &attributes);
  820.   valuemask = 0;
  821.   attributes.background_pixel = WHITE;
  822.   valuemask |= CWBackPixel;
  823.   attributes.border_pixel = BLACK;
  824.   valuemask |= CWBorderPixel;
  825.   attributes.event_mask = ButtonPressMask | ExposureMask;
  826.   valuemask |= CWEventMask;
  827.   attributes.override_redirect = True;
  828.   valuemask |= CWOverrideRedirect;
  829.   attributes.win_gravity = UnmapGravity;
  830.   valuemask |= CWWinGravity;
  831.   quitwindow = XCreateWindow(mydisplay, topwindow, 0, 0, 10, 10, 0,
  832.                  CopyFromParent, InputOutput, CopyFromParent,
  833.                  valuemask, &attributes);
  834.   newwindow = XCreateWindow(mydisplay, topwindow, 0, 0, 10, 10, 0,
  835.                 CopyFromParent, InputOutput, CopyFromParent,
  836.                 valuemask, &attributes);
  837.   undowindow = XCreateWindow(mydisplay, topwindow, 0, 0, 10, 10, 0,
  838.                  CopyFromParent, InputOutput, CopyFromParent,
  839.                  valuemask, &attributes);
  840.   startwindow = XCreateWindow(mydisplay, topwindow, 0, 0, 10, 10, 0,
  841.                    CopyFromParent, InputOutput, CopyFromParent,
  842.                    valuemask, &attributes);
  843.   changewindow = XCreateWindow(mydisplay, topwindow, 0, 0, 10, 10, 0,
  844.                    CopyFromParent, InputOutput, CopyFromParent,
  845.                    valuemask, &attributes);
  846.   if (fontpattern != NULL) {
  847.     fontnames = XListFonts(mydisplay, fontpattern, MAXFONTS, &fontnum);
  848.     if (fontnames != NULL && fontnum > 0) {
  849.       for (i = 0; i < fontnum; i++)
  850.     fontstructarray[i] = XLoadQueryFont(mydisplay, fontnames[i]);
  851.       qsort((char *) fontstructarray, fontnum, sizeof(XFontStruct *), font_cmp);
  852.       XFreeFontNames(fontnames);
  853.       goto got_fonts;
  854.     } else
  855.       fprintf(stderr, "%s: no fonts found with pattern %s.\n",
  856.           *argv, fontpattern);
  857.   }
  858.   fontnames = XListFonts(mydisplay, DEFAULTFONTPATTERN, MAXFONTS, &fontnum);
  859.   if (fontnames == NULL || fontnum == 0) {
  860.     fontstructarray[0] = XLoadQueryFont(mydisplay, "fixed");
  861.     fontnum = 1;
  862.   } else {
  863.     for (i = 0; i < fontnum; i++)
  864.       fontstructarray[i] = XLoadQueryFont(mydisplay, fontnames[i]);
  865.     qsort((char *) fontstructarray, fontnum, sizeof(XFontStruct *), font_cmp);
  866.     XFreeFontNames(fontnames);
  867.   }
  868.  got_fonts:
  869.   stonegc[0] = XCreateGC(mydisplay, topwindow, 0, 0);
  870.   XSetForeground(mydisplay, stonegc[0], YELLOW);
  871.   stonegc[1] = XCreateGC(mydisplay, topwindow, 0, 0);
  872.   XSetForeground(mydisplay, stonegc[1], RED);
  873.   buttongc = XCreateGC(mydisplay, topwindow, 0, 0);
  874.   XSetBackground(mydisplay, buttongc, WHITE);
  875.   XSetForeground(mydisplay, buttongc, BLACK);
  876.   textgc = XCreateGC(mydisplay, topwindow, 0, 0);
  877.   XSetBackground(mydisplay, textgc, WHITE);
  878.   XSetForeground(mydisplay, textgc, BLACK);
  879.   recalculate(myhint.width, myhint.height);
  880.   levelnumstring[0] = '0' + level;
  881.   write_prog(levelnumstring[0]);
  882.   XMapSubwindows(mydisplay, topwindow);
  883.   XMapRaised(mydisplay, topwindow);
  884.   while (1) {
  885.     while (XEventsQueued(mydisplay, QueuedAfterReading) > 0) {
  886.       XNextEvent(mydisplay, &myevent);
  887.       switch (myevent.type) {
  888.       case Expose:
  889.     if (myevent.xexpose.count == 0) {
  890.       if (myevent.xexpose.window == boardwindow) {
  891.         XDrawArcs(mydisplay, boardwindow, textgc, holes, columns * rows);
  892.         if (stone_n[0] > 0)
  893.           XFillArcs(mydisplay, boardwindow,
  894.             stonegc[0], stone[0], stone_n[0]);
  895.         if (stone_n[1] > 0)
  896.           XFillArcs(mydisplay, boardwindow,
  897.             stonegc[1], stone[1], stone_n[1]);
  898.       } else if (myevent.xexpose.window == quitwindow) {
  899.         XDrawImageString(mydisplay, quitwindow, buttongc,
  900.                  quitposx, quitposy, "Quit", 4);
  901.       } else if (myevent.xexpose.window == newwindow) {
  902.         XDrawImageString(mydisplay, newwindow, buttongc,
  903.                  newposx, newposy, "New", 3);
  904.       } else if (myevent.xexpose.window == undowindow) {
  905.         XDrawImageString(mydisplay, undowindow, buttongc,
  906.                  undoposx, undoposy, "Undo", 4);
  907.       } else if (myevent.xexpose.window == startwindow) {
  908.         XDrawImageString(mydisplay, startwindow, buttongc,
  909.                  startposx, startposy, "Start", 5);
  910.       } else if (myevent.xexpose.window == changewindow) {
  911.         XDrawImageString(mydisplay, changewindow, buttongc,
  912.                  changeposx, changeposy, "Change", 6);
  913.       } else if (myevent.xexpose.window == topwindow) {
  914.         XDrawImageString(mydisplay, topwindow, textgc,
  915.                  text1x, levely, "Level: ", 7);
  916.         XDrawImageString(mydisplay, topwindow, textgc,
  917.                  text2x, levely, levelnumstring, 1);
  918.         XDrawImageString(mydisplay, topwindow, textgc,
  919.                  text1x, humany, "You: ", 5);
  920.         XDrawImageString(mydisplay, topwindow, textgc,
  921.                  text2x, humany, playercolor[1 - c_index],
  922.                  strlen(playercolor[1 - c_index]));
  923.         XDrawImageString(mydisplay, topwindow, textgc,
  924.                  text1x, compy, "Me: ", 4);
  925.         XDrawImageString(mydisplay, topwindow, textgc,
  926.                  text2x, compy, playercolor[c_index],
  927.                  strlen(playercolor[c_index]));
  928.         XDrawImageString(mydisplay, topwindow, textgc,
  929.                  text1x, movey, messagestring[message_index],
  930.                  strlen(messagestring[message_index]));
  931.       }
  932.     }
  933.     break;
  934.       case MappingNotify:
  935.     XRefreshKeyboardMapping((XMappingEvent *) &myevent);
  936.     break;
  937.       case ConfigureNotify:
  938.     recalculate(myevent.xconfigure.width, myevent.xconfigure.height);
  939.     XMapSubwindows(mydisplay, topwindow);
  940.     break;
  941.       case ButtonPress:
  942.     if (myevent.xbutton.window == quitwindow)
  943.       goto xvier_end;
  944.     if (myevent.xbutton.window == newwindow)
  945.       write_prog('n');
  946.     else if (myevent.xbutton.window == undowindow)
  947.       write_prog('u');
  948.     else if (myevent.xbutton.window == changewindow) {
  949.       GC tmpgc;
  950.       char *stmp;
  951.  
  952.       tmpgc = stonegc[0];
  953.       stonegc[0] = stonegc[1];
  954.       stonegc[1] = tmpgc;
  955.       stmp = playercolor[0];
  956.       playercolor[0] = playercolor[1];
  957.       playercolor[1] = stmp;
  958.       stmp = messagestring[0];
  959.       messagestring[0] = messagestring[1];
  960.       messagestring[1] = stmp;
  961.       if (stone_n[0] > 0)
  962.         XFillArcs(mydisplay, boardwindow, stonegc[0], stone[0], stone_n[0]);
  963.       if (stone_n[1] > 0)
  964.         XFillArcs(mydisplay, boardwindow, stonegc[1], stone[1], stone_n[1]);
  965.       Repaint_topwindow();
  966.     } else if (myevent.xbutton.window == startwindow) {
  967.       if (processing || message_index > 1 ||
  968.           stone_n[0] > 0 || stone_n[1] > 0)
  969.         XBell(mydisplay, 0);
  970.       else {
  971.         GC tmpgc;
  972.         char *stmp;
  973.  
  974.         write_prog('s');
  975.         tmpgc = stonegc[0];
  976.         stonegc[0] = stonegc[1];
  977.         stonegc[1] = tmpgc;
  978.         stmp = playercolor[0];
  979.         playercolor[0] = playercolor[1];
  980.         playercolor[1] = stmp;
  981.         stmp = messagestring[0];
  982.         messagestring[0] = messagestring[1];
  983.         messagestring[1] = stmp;
  984.         c_index = 1 - c_index;
  985.         Repaint_topwindow();
  986.       }
  987.     } else if (myevent.xbutton.window == boardwindow) {
  988.       if (processing || message_index > 1)
  989.         XBell(mydisplay, 0);
  990.       else {
  991.         if ((myevent.xbutton.x % (piece_width + piece_dx)) > piece_dx) {
  992.           int col = myevent.xbutton.x / (piece_width + piece_dx);
  993.  
  994.           if (col < columns)
  995.         if (columnfill[col] < rows) {
  996.           write_prog('a' + col);
  997.           domove(1 - c_index, col);
  998.           message(1 - message_index);
  999.         } else
  1000.           XBell(mydisplay, 0);
  1001.         }
  1002.       }
  1003.     }
  1004.     break;
  1005.       case KeyPress:
  1006.     if (XLookupString((XKeyEvent *) &myevent, text, 10, &mykey, 0) == 1) {
  1007.       switch (text[0]) {
  1008.       case 'q': case 'Q':
  1009.         goto xvier_end;
  1010.       case 'a': case 'b': case 'c': case 'd': case 'e':
  1011.       case 'f': case 'g': case 'h': case 'i': case 'j':
  1012.       case 'k': case 'l': case 'm':
  1013.         if (processing || message_index > 1 ||
  1014.         text[0] - 'a' >= columns || columnfill[text[0] - 'a'] >= rows)
  1015.           XBell(mydisplay, 0);
  1016.         else {
  1017.           write_prog(text[0]);
  1018.           domove(1 - c_index, text[0] - 'a');
  1019.           message(1 - message_index);
  1020.         }
  1021.         break;
  1022.       case 's': case 'S':
  1023.         if (processing || message_index > 1 ||
  1024.         stone_n[0] > 0 || stone_n[1] > 0)
  1025.           XBell(mydisplay, 0);
  1026.         else {
  1027.           GC tmpgc;
  1028.           char *stmp;
  1029.  
  1030.           write_prog('s');
  1031.           tmpgc = stonegc[0];
  1032.           stonegc[0] = stonegc[1];
  1033.           stonegc[1] = tmpgc;
  1034.           stmp = playercolor[0];
  1035.           playercolor[0] = playercolor[1];
  1036.           playercolor[1] = stmp;
  1037.           stmp = messagestring[0];
  1038.           messagestring[0] = messagestring[1];
  1039.           messagestring[1] = stmp;
  1040.           c_index = 1 - c_index;
  1041.           Repaint_topwindow();
  1042.         }
  1043.         break;
  1044.       case 'N': case 'U':
  1045.         text[0] += 'a' - 'A';
  1046.       case 'n': case 'u':
  1047.       case '0': case '1': case '2': case '3': case '4':
  1048.       case '5': case '6': case '7': case '8': case '9':
  1049.         write_prog(text[0]);
  1050.         break;
  1051.       case 'C':
  1052.         {
  1053.           GC tmpgc;
  1054.           char *stmp;
  1055.  
  1056.           tmpgc = stonegc[0];
  1057.           stonegc[0] = stonegc[1];
  1058.           stonegc[1] = tmpgc;
  1059.           stmp = playercolor[0];
  1060.           playercolor[0] = playercolor[1];
  1061.           playercolor[1] = stmp;
  1062.           stmp = messagestring[0];
  1063.           messagestring[0] = messagestring[1];
  1064.           messagestring[1] = stmp;
  1065.         }
  1066.         if (stone_n[0] > 0)
  1067.           XFillArcs(mydisplay, boardwindow,
  1068.             stonegc[0], stone[0], stone_n[0]);
  1069.         if (stone_n[1] > 0)
  1070.           XFillArcs(mydisplay, boardwindow,
  1071.             stonegc[1], stone[1], stone_n[1]);
  1072.         Repaint_topwindow();
  1073.         break;
  1074.       default:
  1075.         XBell(mydisplay, 0);
  1076.         break;
  1077.       }
  1078.     }
  1079.     break;
  1080.       }
  1081.     }
  1082.     XFlush(mydisplay);
  1083. #ifdef NO_SELECT
  1084.     poll(pfd, npfd, 500);
  1085.     if (pfd[1].revents == POLLIN) {
  1086. #else
  1087.     readfds = fullfds;
  1088. #ifdef NO_FD_SET
  1089.     select(32, &readfds, 0, 0, &selectval);
  1090.     if (readfds & (1 << pipei[0])) {
  1091. #else
  1092.     select(FD_SETSIZE, &readfds, (fd_set *) 0, (fd_set *) 0, &selectval);
  1093.     if (FD_ISSET(pipei[0], &readfds)) {
  1094. #endif
  1095. #endif
  1096.       char answer;
  1097.  
  1098.       if (read(pipei[0], &answer, 1) < 1) {
  1099.     fprintf(stderr, "%s: read from xvier_prog failed\n", *argv);
  1100.     exit(1);
  1101.       }
  1102.       if (processing == 0) {
  1103.     fprintf(stderr, "%s: unexpected read from xvier_prog\n", *argv);
  1104.     goto xvier_end;
  1105.       }
  1106.       processing = 0;
  1107.       XDefineCursor(mydisplay, topwindow, cursor_normal);
  1108.       switch (answer) {
  1109.       case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g':
  1110.       case 'h': case 'i': case 'j': case 'k': case 'l': case 'm':
  1111.     if (answer - 'a' >= columns ||
  1112.         columnfill[answer - 'a'] >= rows) {
  1113.       fprintf(stderr, "%s: wrong move %c from xvier_prog\n",
  1114.           *argv, answer);
  1115.       goto xvier_end;
  1116.     }
  1117.     domove(c_index, answer - 'a');
  1118.     message(1 - message_index);
  1119.     break;
  1120.       case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G':
  1121.       case 'H': case 'I': case 'J': case 'K': case 'L': case 'M':
  1122.     if (answer - 'A' >= columns ||
  1123.         columnfill[answer - 'A'] >= rows) {
  1124.       fprintf(stderr, "%s: wrong move %c from xvier_prog\n",
  1125.           *argv, answer);
  1126.       goto xvier_end;
  1127.     }
  1128.     domove(c_index, answer - 'A');
  1129.     message(2);
  1130.     break;
  1131.       case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T':
  1132.       case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z':
  1133.     if (answer - 'N' >= columns ||
  1134.         columnfill[answer - 'N'] >= rows) {
  1135.       fprintf(stderr, "%s: wrong move %c from xvier_prog\n",
  1136.           *argv, answer);
  1137.       goto xvier_end;
  1138.     }
  1139.     domove(c_index, answer - 'N');
  1140.       case 'z':
  1141.     message(4);
  1142.     break;
  1143.       case 'w':
  1144.     message(3);
  1145.     break;
  1146.       case '0': case '1': case '2': case '3': case '4':
  1147.       case '5': case '6': case '7': case '8': case '9':
  1148.     levelnumstring[0] = answer;
  1149.     Repaint_topwindow();
  1150.     break;
  1151.       case 'n':
  1152.     XClearArea(mydisplay, boardwindow, 0, 0, 0, 0, False);
  1153.     XDrawArcs(mydisplay, boardwindow, textgc, holes, columns * rows);
  1154.     stone_n[0] = stone_n[1] = 0;
  1155.     for (i = 0; i < columns; i++)
  1156.       columnfill[i] = 0;
  1157.     message_index = 1 - c_index;
  1158.     Repaint_topwindow();
  1159.     break;
  1160.       case 'u':
  1161.     undomove(c_index);
  1162.       case 'v':
  1163.     undomove(1 - c_index);
  1164.     message_index = 1 - c_index;
  1165.     Repaint_topwindow();
  1166.     break;
  1167.       default:
  1168.     XBell(mydisplay, 0);
  1169.     break;
  1170.       }
  1171.     }
  1172.     if (processing)
  1173.       change_cursor();
  1174.   }
  1175.  xvier_end:
  1176.   XCloseDisplay(mydisplay);
  1177.   kill(pid, SIGKILL);
  1178.   exit(0);
  1179. }
  1180.